package com.example.mybatisplus.plugs;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.example.mybatisplus.common.RealtyConstants;
import com.example.mybatisplus.common.RealtyDataPermission;
import com.example.mybatisplus.utils.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class CustomDataPermissionHandler implements MultiDataPermissionHandler {
    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
        log.info("PRO CustomDataPermissionHandler.getSqlSegment table:{},where:{},mappedStatementId:{}", table.getName(), where, mappedStatementId);
        try {
            if (!isQueryMethod(mappedStatementId)) return null;

            // 判断是否是登录获取数据，是则不进行数据权限控制
            Boolean flag = UserContextHolder.get();
            if (flag != null && flag) {
                log.info("PRO CustomDataPermissionHandler.getSqlSegment login fetch data, no data permission control");
                return null;
            }
            // 判断角色是否是经营户
            // LoginUser loginUser = SecurityUtils.getLoginUser();
            // SysUser sysUser = loginUser.getSysUser();
            // List<SysRole> roleList = sysUser.getRoles();
            // if (CollectionUtil.isNotEmpty(roleList)) {
            //     long count = roleList.stream().map(SysRole::getRoleKey).filter(StringUtils::isNotBlank).filter("jyh"::equals).count();
            //     if (count <= 0) return null;
            // }
            Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringPool.DOT)));

            if (!clazz.isAnnotationPresent(RealtyDataPermission.class)) return null;

            RealtyDataPermission realtyDataPermission = clazz.getAnnotation(RealtyDataPermission.class);
            String tableName = realtyDataPermission.tableName();
            String name = table.getName();
            if (!name.equalsIgnoreCase(tableName)) return null;

            String[] excludes = realtyDataPermission.excludes();
            if (excludes != null) {
                String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringPool.DOT) + 1).toLowerCase();
                if (Arrays.asList(excludes).contains(methodName)) return null;
            }
            String type = realtyDataPermission.type();

            // todo 这里的权限列表需要更改
            List<String> customerIdList = new ArrayList<>();
            List<String> stallIdList = new ArrayList<>();
            String perValue;
            if (RealtyConstants.MAP_KEY_CUSTOMER.equals(type)) {
                perValue = StrUtil.join(StringPool.COMMA, customerIdList);
            } else if (RealtyConstants.MAP_KEY_STALLS.equals(type)) {
                perValue = StrUtil.join(StringPool.COMMA, stallIdList);
            } else {
                return null;
            }
            if (StringUtils.isBlank(perValue)) return CCJSqlParserUtil.parseCondExpression("1=0");

            String field = realtyDataPermission.field();
            if (StringUtils.isBlank(field)) return null;

            if (ObjectUtil.isNotNull(table.getAlias()) && StrUtil.isNotBlank(table.getAlias().getName())) {
                field = table.getAlias().getName() + StringPool.DOT + field;
            }

            String rangeValue = "( " + perValue + " )";
            if (realtyDataPermission.association()) {
                String associationSql = realtyDataPermission.associationSql();
                if (StrUtil.isNotBlank(associationSql)) {
                    rangeValue = associationSql.replace("{value}", perValue);
                }
            }
            String appendSqlStr = field + " in " + rangeValue;


            if (StrUtil.isBlank(appendSqlStr)) return null;

            Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);

            // if (where == null) return appendExpression;

            // AndExpression expression = new AndExpression(where, appendExpression);
            // log.info("PRO CustomDataPermissionHandler.getSqlSegment table:{},where:{},mappedStatementId:{}, expression:{}", table.getName(), where, mappedStatementId, expression);
            log.info("PRO CustomDataPermissionHandler.getSqlSegment table:{},where:{},mappedStatementId:{}, expression:{}", table.getName(), where, mappedStatementId, appendExpression);

            return appendExpression;
        } catch (Exception e) {
            log.error("ERROR CustomDataPermissionHandler error table:{},where:{},mappedStatementId:{}, cause:", table.getName(), where, mappedStatementId, e);
            return null;
        }
    }

    private boolean isQueryMethod(String mappedStatementId) {
        if (mappedStatementId == null || !mappedStatementId.contains(StringPool.DOT)) return false;

        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringPool.DOT) + 1).toLowerCase();
        String[] queryPrefixes = {"select", "get", "find", "list", "page", "query", "count", "search"};
        for (String p : queryPrefixes) {
            if (methodName.startsWith(p)) return true;

        }
        return false;
    }
}